//
//  ffield.swift
//  xzbuyer
//
//  Created by zhuxietong on 2021/2/9.
//

import Foundation
import Eelay
import RxSwift
extension Array where Self.Element == FField {
    public func clear(){
        for f in self {
            f.clear()
        }
    }
    
    public func detailCheck()->(valid:Bool,values:[String:Any],message:String){
        var values:[String:Any] = [:]
        if let f = self.first{
            let ctr = f.mo.controller
            ctr?.view.endEditing(true)
        }
        for f in self {
            if f.name.count > 0{
                switch f.verifyResult {
                case .error(let err):
                    return (false,values,err)
                case .nil:
                  
                    return (false,values,f.emptyTip)
                default:
           
                    values[f.name] = f.sumbitValue
                }
            }
        }
        return (true,values,"校验成功")
    }
    
    public func check(alert:Bool = true) ->(valid:Bool,values:[String:Any]){
        var values:[String:Any] = [:]
        if let f = self.first{
            let ctr = f.mo.controller
            ctr?.view.endEditing(true)
        }
        for f in self {
            if f.name.count > 0{
                switch f.verifyResult {
                case .error(let err):
                    if alert{
                        err.alert()
                    }
                    return (false,values)
                case .nil:
                    if alert{
                        f.emptyTip.alert()
                    }
                    return (false,values)
                default:
           
                    values[f.name] = f.sumbitValue
                }
            }
        }
        return (true,values)
    }
}

open class FField:MoDisplayNode{
    
    open func clear() {
        update(value: "", edit: .clear)
    }
    open var sumbitValue:Any{
        let foramt = props.format
        foramt.valueObject = value
        return foramt.formValue
    }
    open var valueDisplay:String{
        return "\(value)"
    }
    open override var description: String{
        get{
            return "\(props)"
        }
    }
    public var initProps:[FProps] = []
    public var valueStyle:[UICss] = [.color(._foreground),.font(.systemFont(ofSize: 14))]
    public var placeHolderStyle:[UICss] = [.color(._weak),.font(.systemFont(ofSize: 14))]
    public var labelStyle:[UICss] = [.color(._foreground),.font(.systemFont(ofSize: 14))]{
        didSet{
            updateDispaly()
        }
    }
    public let lableNode = ASTextNode2()

    open override func willLayoutRules() {
        loadProps()
    }
    public required init(propsArray props:[FProps]){
        self.initProps = props
        super.init()
        self.props = props + self.defaultProps
        for p in self.props {
            switch p {
            case .value(let v):
                self.value = v
            default:
                break
            }
        }
        didSetProps()
        loadProps()
        didInit()
    }
    public init(props:FProps...) {
        self.initProps = props
        super.init()
        self.props = props + self.defaultProps
        for p in self.props {
            switch p {
            case .value(let v):
                self.value = v
            default:
                break
            }
        }
        didSetProps()
        loadProps()
        didInit()
    }
    
    open func didInit(){
        
    }
    
    
    open func didLoadProps() {
        lableNode.attributedText = _lable
    }
    
    open func loadProps() {
        for p in props {
            switch p {
            case .name(let name,let title):
                self.name = name
                self.title = title
            case .value(let value):
                self.value = value;
            case .model(let model):
                mo.model = model.mutable_dictionary
            default:
                break
            }
        }
        didLoadProps()
        updateDispaly()
    }
    
    open override func mo_model_reload() {
        lableNode.attributedText = _lable
    }
    
    open var _lable:NSAttributedString{
        get{
            if props.required{
                return label.ui.font(font: labelStyle.font).color(color: labelStyle.color).astring + " *".ui.bfont14.color(color: .systemRed).astring
            }
            
            return label.ui.font(font: labelStyle.font).color(color: labelStyle.color).astring
        }
    }
    
    
    public required init() {
        super.init()
        didInit()
    }
    public let status:PublishSubject<(String,Any,FEdit,NSMutableDictionary)> = PublishSubject<(String,Any,FEdit,NSMutableDictionary)>()
    public let changeFrame:PublishSubject<ASDisplayNode> = PublishSubject<ASDisplayNode>()

    
    open var defaultProps:[FProps]{
        get{
            return [.type(.input),.verify(.reg("\\S+"))]
        }
    }
    public var props:[FProps] = []{
        didSet{
            didSetProps()
        }
    }
    
    open func didSetProps() {
        
    }
    
    public var name:String = ""
    public var title:String = ""
    public var value:Any = ""{
        didSet{
            didSetValue(value: value)
        }
    }
    open func didSetValue(value:Any) {
        
    }
    
    
    open func updateDispaly() {
        
    }
    
    open var statusObject:NSMutableDictionary{
        get{
            return mo.model
        }
    }
    
    open func update(value:Any,edit:FEdit){
        self.value = value
        switch edit {
        case .select,.input:
            status.onNext((name,value,edit,statusObject))
            didLoadProps()
            updateDispaly()

        case .reply:
            didLoadProps()
            updateDispaly()
        default:
            didLoadProps()
            updateDispaly()
        }
    }
    
    open func update(_ prop:FProps){
        props.update(prop)
        loadProps()
    }
    
    
    
    
}


//extension Array where
extension FField{
    open var label:String{
        get{
            return props.label
        }
    }
    
    
    
    open var placeholder:String{
        get{
            for p in props {
                switch p {
                case .placeholder(let tip):
                    return tip
                default:
                    break
                }
            }
        
            return "请" + props.type.name + title
        }
    }
    
    open var errorTip:String{
        get{
            for p in props {
                switch p {
                case .errorTip(let tip):
                    return tip
                default:
                    break
                }
            }
            return "请" + props.type.name + "有效的" + label
        }
    }
    
    open var emptyTip:String{
        get{
            for p in props {
                switch p {
                case .emptyTip(let tip):
                    return tip
                default:
                    break
                }
            }
            for p in props {
                switch p {
                case .placeholder(let tip):
                    return tip
                default:
                    break
                }
            }
            return "请" + props.type.name + title
        }
    }
    
    open var verifyResult:FVerifyResult{
        get{
            switch self.verify {
            case .method(let m):
                let result = m(self.value)
                return result
            case .reg(let reg):
                let mach = "\(value)".mach(reg)
                if mach{
                    return .success(value: value)
                }
                if "\(value)".len < 1{
                    return .nil
                }
                return .error(errorTip)
            }
        }
    }
    
    open var verify:FVerify{
        get{
            for p in props {
                switch p {
                case .verify(let f):
                    return f
                default:
                    break
                }
            }
            return .method {[weak self] (f) -> FVerifyResult in
                let v = self?.value ?? ""
                if ("\(v)".len > 0){
                    return .success(value: v)
                }else{
                    return .nil
                }
            }
        }
    }
}
